package mc.contents.service.impl;

import com.taobao.api.domain.Item;
import com.taobao.api.domain.User;
import mc.contents.dao.*;
import mc.contents.pojo.persistence.QueryRecord;
import mc.contents.pojo.persistence.RankHistory;
import mc.contents.pojo.persistence.RankItemHistory;
import mc.contents.pojo.persistence.ShopKeyword;
import mc.contents.pojo.view.Rank;
import mc.contents.pojo.view.RankItem;
import mc.contents.pojo.view.ReshelfItem;
import mc.contents.pojo.view.Shopcard;
import mc.contents.service.ICrawService;
import mc.contents.util.IPSeeker;
import mc.contents.util.TimeUtils;
import mc.contents.web.common.CrawResult;
import mc.contents.web.request.RankCrawRequest;
import mc.contents.web.request.ReshelfCrawRequest;
import mc.contents.web.result.RankCrawResult;
import mc.contents.web.result.ReshelfCrawResult;
import mc.support.crawler.SortType;
import mc.support.crawler.SourceType;
import mc.support.service.common.ICacheService;
import mc.support.service.common.ITaobaoTopAPIService;
import mc.support.support.function.Closure;
import mc.support.taobao.api.GetUsersReq;
import mc.support.taobao.api.fields.GetItemsFields;
import mc.support.taobao.api.fields.GetItemsListFields;
import mc.support.taobao.api.fields.GetUsersFields;
import mc.support.util.PlainUtil;
import mc.support.util.SliceUtil;
import mc.support.util.TaobaoPojoUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;

/**
 * Created by LuoHui on 14-11-25.
 */
@Service("crawService")
public class CrawlServiceImpl implements ICrawService {
    @Resource
    private MingRankHistoryMapper mingRankHistoryMapper;
    @Resource
    private MingRankItemHistoryMapper mingRankItemHistoryMapper;
    @Resource
    private QianRankHistoryMapper qianRankHistoryMapper;
    @Resource
    private QianRankItemHistoryMapper qianRankItemHistoryMapper;
    @Autowired
    private ITaobaoTopAPIService taobaoTopAPIService;
    @Resource
    private ThesauriMapper thesauriMapper;
    @Resource
    private QianTbItemMapper qianTbItemMapper;
    @Resource
    private MingTbItemMapper mingTbItemMapper;

    private static final GetItemsListFields fields = new GetItemsListFields().nick().num_iid().title().price().delist_time().pic_url().detail_url();

    private static final GetItemsFields volume_fields = new GetItemsFields().nick().num_iid().volume();

    @Autowired
    private ICacheService cacheService;


    @Override
    public ShopKeyword getByKeyword(String keyword) {
        return thesauriMapper.getByKeyword(keyword);
    }

    @Override
    public boolean queryBusy(String sellerId) {
        QueryRecord record = (QueryRecord) cacheService.readObjectFromCache(getRedisKey(sellerId));
        if(record!=null){
            long t = 1*60*1000L;
            if(new Date().getTime() - record.getQueryTime().getTime() < t){
                return true;
            }
        }
        return false;
    }

    @Override
    public void writeQueryTime(String sellerId) {
        QueryRecord record = new QueryRecord(sellerId,new Date());
        cacheService.writeObjectToCache(record,getRedisKey(sellerId),3600);
    }

    private String getRedisKey(String sellerId) {
        return cacheService.generateCacheKey(CrawlServiceImpl.class,"QueryRecord",sellerId);
    }

    @Override
    public Set<ReshelfItem> getReshelfItems( ReshelfCrawRequest crawRequest, List<CrawResult> results ) {
        Set<Long> idSet = new HashSet<>(  );
        Set<ReshelfItem> items = new HashSet<>(  );
        String sessionKey = crawRequest.getSessionKey();
        for ( CrawResult crawResult : results ) {
            ReshelfCrawResult result = (ReshelfCrawResult) crawResult;
            List<ReshelfItem> l = result.getItems();
            if( l!=null&&!l.isEmpty() ){
                for ( int i = 0; i < l.size(); i++ ) {
                    ReshelfItem item = l.get( i );
                    item.setPageIndex( result.getPageIndex()+1 );
                    item.setIndexInPage( i+1 );
                    items.add( item );
                    idSet.add( Long.parseLong( item.getNum_iid() ) );
                }
            }
        }
        Float minPrice = crawRequest.getMinPrice();
        Float maxPrice = crawRequest.getMaxPrice();
        setItemAttr( sessionKey,idSet,items );
        return getItemsByPriceLimit( items,minPrice,maxPrice );
    }

    private void setItemAttr( String sessionKey, Set<Long> idSet, Set<ReshelfItem> items ) {
        List<Item> itemList = taobaoTopAPIService.getItemsList(sessionKey, idSet, fields);
        if( itemList!=null&&!itemList.isEmpty() ){
            Map<Long,Item> map = PlainUtil.buildMapByList( itemList, new Closure<Long, Item>() {
                @Override
                public Long call( Item item ) {
                    return item.getNumIid();
                }
            } );
            Set<String> nicks = new HashSet<>(  );
            for ( ReshelfItem item : items ) {
                Item i = map.get( Long.parseLong( item.getNum_iid() ) );
                if ( i != null ) {
                    nicks.add( i.getNick() );
                    item.setNick( i.getNick() );
                    item.setReserve_price( i.getPrice() );
                    item.setTitle( i.getTitle() );
                    item.setDetail_url( i.getDetailUrl() );
                    item.setPic_url( i.getPicUrl() );
                    item.setDelist_time( TimeUtils.format( i.getDelistTime() ) );
                }
            }
            int len = nicks.size();
            //number of item is limit by 40 once.
            if( len>40 ){
                List<String> total = new ArrayList<>( nicks );
                List<String> slice = null;
                int begin = 0;
                final int offset = 40;
                while ( true ){
                    slice = SliceUtil.doSlice( total, begin, offset - 1 );
                    if( null==slice || 0==slice.size() ){
                        break;
                    }
                    setItemCredit( new HashSet<String>( slice ),items );
                    begin += offset;
                }
            }else{
                setItemCredit(nicks,items);
            }
        }
    }

    private void setItemCredit( Set<String> nicks, Set<ReshelfItem> items ) {
        GetUsersFields getUsersFields = new GetUsersFields().nick().user_id().seller_credit().type();
        GetUsersReq getUsersReq = new GetUsersReq().nicks( nicks ).fields( getUsersFields );
        List<User> userList = taobaoTopAPIService.getUsers( getUsersReq );
        if( userList!=null&&!userList.isEmpty() ){
            Map<String,User> map = PlainUtil.buildMapByList( userList, new Closure<String, User>() {
                @Override
                public String call( User u ) {
                    return u.getNick();
                }
            } );
            for ( ReshelfItem item : items ) {
                User u = map.get( item.getNick() );
                if ( u != null ) {
                    Shopcard shopcard = new Shopcard();
                    shopcard.setIsTmall( "B".equals( u.getType() ) ? 1 : 0);
                    shopcard.setSellerCredit( Integer.parseInt( String.valueOf( u.getSellerCredit().getLevel() ) ) );
                    item.setShopcard( shopcard );
                }
            }

        }
    }

    private Set<ReshelfItem> getItemsByPriceLimit( Set<ReshelfItem> items,Float minPrice,Float maxPrice ) {
        Set<ReshelfItem> l = new HashSet<>(  );
        for ( ReshelfItem item : items ) {
            String reserve_price = item.getReserve_price();
            if( maxPrice==null ){
                l.add( item );
            }else{
                if( reserve_price!=null && minPrice<=Float.parseFloat( reserve_price ) && Float.parseFloat( reserve_price )<=maxPrice ){
                    l.add( item );
                }
            }
        }
        return l;
    }

    public static void main(String[] args) {
        System.out.println();
    }

    @Override
    public Set<Rank> getRanks( RankCrawRequest crawRequest, List<CrawResult> RankCrawResults ) {
        String qn = crawRequest.getQn();
        boolean isQian = !"false".equals(qn);
        Set<Rank> ranks = filter(crawRequest, RankCrawResults, isQian);
        saveAsHistory(crawRequest,ranks, crawRequest.getNick(),isQian);
        return ranks;
    }

    private Set<Rank> filter( RankCrawRequest crawRequest, List<CrawResult> RankCrawResults,boolean isQian ) {
        Long sellerId = crawRequest.getSellerId();
        String sessionKey = crawRequest.getSessionKey();
        boolean byApi = crawRequest.isByApi();
        String nick = crawRequest.getNick();
        List<Item> items = getOnSaleItems( nick,sellerId,sessionKey,isQian,byApi );

        Map<Long,Item> map = PlainUtil.buildMapByList( items,new Closure<Long, Item>() {
            @Override
            public Long call( Item item ) {
                return item.getNumIid();
            }
        } );

        Set<Rank> ranks = new HashSet<>(  );
        if( RankCrawResults!=null && !RankCrawResults.isEmpty() ){
            for ( CrawResult crawResult : RankCrawResults ) {
                RankCrawResult rankCrawResult = (RankCrawResult) crawResult;
                Integer pageIndex = rankCrawResult.getPageIndex();
                List<RankItem> itemList = rankCrawResult.getItems();
                if( itemList!=null ){
                    int size = itemList.size();
                    if( size>0 ){
                        for ( int i = 0; i < size; i++ ) {
                            RankItem item = itemList.get( i );
                            Long id;
                            if( item!=null && (id=item.getNumIid())!=null ){
                                if(map.containsKey( id )){
                                    Item item0 = map.get( id );
                                    Rank rank = convertRank(item,item0, crawRequest,pageIndex,i,id);
                                    ranks.add( rank );
                                }
                            }
                        }
                    }
                }
            }
        }
        return ranks;
    }

    private Rank convertRank(RankItem item, Item item0,RankCrawRequest crawRequest,Integer pageIndex,int i,Long id) {
        String keyword = crawRequest.getKeyword();
        SortType sortType = SortType.valueOf( crawRequest.getSortType() );
        SourceType sourceType = SourceType.valueOf( crawRequest.getSourceType() );

        Rank rank = new Rank();
        rank.setPageIndex(pageIndex + 1);
        rank.setKeyword(keyword);
        rank.setIndexInPage(i + 1);
        rank.setSourceType(sourceType);
        rank.setSortType(sortType);
        rank.setItemId(id);
        rank.setVolume(item0.getVolume());
        rank.setOuterId(item0.getOuterId());
        rank.setTitle(item0.getTitle());
        rank.setDelistTime(item0.getDelistTime());
        rank.setImgUrl(TaobaoPojoUtil.getMiniImgUrl(item0.getPicUrl()));
        rank.setDetailUrl( item0.getDetailUrl() );
        rank.setIp( item.getIp() );
        if( StringUtils.isNotEmpty(item.getIp())){
            rank.setIpAdd( IPSeeker.getInstance().getCountry( item.getIp() ) );
        }
        return rank;
    }

    @Override
    public void saveAsHistory( RankCrawRequest crawRequest, Set<Rank> ranks, String nick, boolean isQian ) {
        Date now = new Date();
        RankHistory rankHistory = new RankHistory();
        Long sellerId = crawRequest.getSellerId();
        rankHistory.setSellerId(sellerId);
        rankHistory.setKeyword(crawRequest.getKeyword());
        rankHistory.setSourceType(SourceType.valueOf(crawRequest.getSourceType()));
        rankHistory.setSortType(SortType.valueOf(crawRequest.getSortType()));
        rankHistory.setCreateTime(now);
        if( isQian ){
            qianRankHistoryMapper.insertRankHistory(rankHistory);
        }else{
            mingRankHistoryMapper.insertRankHistory(rankHistory);
        }

        Long id = rankHistory.getId();

        if( ranks!=null && !ranks.isEmpty() ){
            List<RankItemHistory> rList = new ArrayList<>(  );
            for ( Rank r : ranks ) {
                RankItemHistory rh = new RankItemHistory();
                rh.setRecordId(id);
                rh.setSellerId(sellerId);
                rh.setItemId(r.getItemId());
                rh.setImgUrl(r.getImgUrl());
                rh.setTitle(r.getTitle());
                rh.setDelistTime(r.getDelistTime());
                rh.setPageIndex(r.getPageIndex());
                rh.setIndexInPage(r.getIndexInPage());
                rh.setIp(r.getIp());
                rh.setIpAdd(r.getIpAdd());
                rList.add( rh );
            }
            if(isQian){
                qianRankItemHistoryMapper.saveRankItemHistory(crawRequest.getSellerId(), rList);
            }else{
                mingRankItemHistoryMapper.saveRankItemHistory( crawRequest.getSellerId(), rList );
            }
        }
    }

    private List<Item> getOnSaleItems(String nick, Long sellerId,String sessionKey, boolean isQian ,boolean byApi) {
        List<Item> l;
        if(isQian){
            l =  qianTbItemMapper.getByNick(nick, sellerId);
        }else{
            l = mingTbItemMapper.getByNick( nick );
        }

        if( !l.isEmpty() ){
            List<Item> items = taobaoTopAPIService.getItems( sessionKey,nick,volume_fields );
            if( items!=null&&!items.isEmpty() ){
                Map<Long,Item> map = PlainUtil.buildMapByList(items, new Closure<Long, Item>() {
                    @Override
                    public Long call(Item item) {
                        return item.getNumIid();
                    }
                });

                for (Item item : l) {
                    Item i = map.get( item.getNumIid() );
                    if(i!=null){
                        item.setVolume( i.getVolume() );
                    }
                }
            }
        }
        return l;
    }
}
